package com.putao.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Validator;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.putao.base.BaseService;
import com.putao.constants.Constants;
import com.putao.domain.SysUser;
import com.putao.enums.SystemEnums;
import com.putao.enums.VerifyCodeEnum;
import com.putao.mapper.SysUserMapper;
import com.putao.redis.service.IRedisService;
import com.putao.result.JsonResult;
import com.putao.service.SysUserService;
import com.putao.utils.AssertUtil;
import com.putao.utils.BarCodeUtils;
import com.putao.utils.StringUtils;
import com.putao.vo.UserVO;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static com.putao.enums.VerifyCodeEnum.VERIFY_CODE_KEY;

@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService, BaseService<SysUser> {

    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private IRedisService redisService;

    @Override
    public JsonResult getByUsername(String username) {
        SysUser sysUser = this.getOne(new QueryWrapper<SysUser>().eq("username", username));
        return returnObject(sysUser, username);
    }

    @Override
    @Transactional
    public JsonResult register(UserVO userVO) {
        AssertUtil.hasText(userVO.getPassword(), "密码不能为空");
        AssertUtil.hasText(userVO.getRepassword(), "确认密码不能为空");
        AssertUtil.hasText(userVO.getEmail(), "邮箱不能为空");
        SysUser sysUser = new SysUser();
        BeanUtil.copyProperties(userVO, sysUser);
        // 1、检查手机号码是否重复、格式是否正确
        // 2、检查用户名是否重复
        this.checkIsEmptyAndRepeat(null, new QueryWrapper<>(), sysUser, "username", "用户名重复了", "用户名不能为空", null, null);
        this.checkIsEmptyAndRepeat(null, new QueryWrapper<>(), sysUser, "phone", "手机号码重复了", "手机号码不能为空", null, null);
        boolean mobile = Validator.isMobile(userVO.getPhone());
        if (!mobile) {
            return JsonResult.argumentError("手机格式错误", userVO, "手机格式错误");
        }
        String code = redisService.get(VERIFY_CODE_KEY.join(userVO.getPhone()));
        if (StringUtils.isBlank(code)) {
            return JsonResult.argumentError("验证码过期或者不存在", userVO, "验证码过期或者不存在");
        }
        if (!userVO.getCode().equals(code)) {
            return JsonResult.argumentError("验证码过期或者不存在", userVO, "验证码过期或者不存在");
        }
        if (!userVO.getRepassword().equals(userVO.getPassword())) {
            return JsonResult.argumentError("两次密码不一致", userVO, "两次密码不一致");
        }
        // 3、初始化
        sysUser.insertInit();
        sysUser.setPassword(new BCryptPasswordEncoder().encode(sysUser.getPassword()));
        this.save(sysUser);
        return null;
    }

    public static void main(String[] args) {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        boolean matches = bCryptPasswordEncoder.matches("123456", "$2a$10$tBziil09zMobK64Vk41M0.ns1491qrwhiFPrviHONWSMKIbhYCmR.");
        System.out.println("matches = " + matches);

//        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
//        //$2a$10$yPM6IkqoB8IToGKALlk6BOsp4G2eCc2hahwT5JSTzq0dwjGFXk0Pu
//        //$2a$10$VIycWJctonDmydQIJa51AuOE9pu.lZIUSFX3Kp3LiMHsZjI65xkhW
//        String encode = passwordEncoder.encode("123456");
//        System.out.println("密码加密：" + encode);
//        //判断密码是否一致
//        boolean matches = passwordEncoder.matches("123456", "$2a$10$yPM6IkqoB8IToGKALlk6BOsp4G2eCc2hahwT5JSTzq0dwjGFXk0Pu");
//        System.out.println("密码是否一致：" + matches);

    }

    @Override
    @Transactional
    public String getQrcode(String oldUuid, String uuid) {
        if (StringUtils.isNotBlank(oldUuid)) {
            redisService.deleteKey(VerifyCodeEnum.QR_CODE_TIME_OUT.join(oldUuid));
        }
        Map<String, Map<String, String>> qrcodeMap = new HashMap<>();
        Map<String, String> map = new HashMap<>();
        map.put("token", uuid);
        qrcodeMap.put("qrcode", map);
        String image2Base64String = BarCodeUtils.getImage2Base64String(JSON.toJSONString(qrcodeMap));
        // 将uuid存入redis，设置超时时间为2分钟, 延迟消息处理时判断uuid是否存在不存在则不需要操作，反之表示还未登录则发送消息给前端，二维码过期
        redisService.setAndTime(VerifyCodeEnum.QR_CODE_TIME_OUT.join(uuid), Constants.ZERO_STR, VerifyCodeEnum.QR_CODE_TIME_OUT.getTime());
        Message<String> message = MessageBuilder.withPayload(uuid).build();
        String format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.sss").format(new Date());
        log.error("发送消息前的当前时间是: " + format);
        // 发送延迟消息 1分钟 1分钟后二维码失效
        rocketMQTemplate.syncSend(SystemEnums.QR_CODE.getDestination(), message, SystemEnums.QR_CODE.getTimeout(), SystemEnums.QR_CODE.getDelayLevel());
        return image2Base64String;
    }

    @Override
    public JsonResult getByPhone(String phone) {
        SysUser sysUser = this.getOne(new QueryWrapper<SysUser>().eq("phone", phone));
        return returnObject(sysUser, phone);
    }
}

